home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / flst200.zip / V7P_SRC.ZIP / VERSION7.C < prev    next >
C/C++ Source or Header  |  1997-06-09  |  28KB  |  932 lines

  1. //--------------------------------------------------------------------------//
  2. //                                                                          //
  3. //                                                                          //
  4. //      ------------         Bit-Bucket Software, Co.                       //
  5. //      \ 10001101 /         Writers and Distributors of                    //
  6. //       \ 011110 /          Freely Available<tm> Software.                 //
  7. //        \ 1011 /                                                          //
  8. //         ------                                                           //
  9. //                                                                          //
  10. //              (C) Copyright 1987-96, Bit Bucket Software Co.              //
  11. //                                                                          //
  12. //                  This module was adapted by Bill Andrus                  //
  13. //                With the usual kibitzing by Vince Perriello               //
  14. //              BinkleyTerm Version7 Nodelist processing module             //
  15. //                                                                          //
  16. //          V7 reimplementation and V7+ support by Thomas Waldmann          //
  17. //          Attention: V7+ works, but is far from being completed.          //
  18. //                                                                          //
  19. //    For complete  details  of the licensing restrictions, please refer    //
  20. //    to the License  agreement,  which  is published in its entirety in    //
  21. //    the MAKEFILE and BT.C, and also contained in the file LICENSE.260.    //
  22. //                                                                          //
  23. //    USE  OF THIS FILE IS SUBJECT TO THE  RESTRICTIONS CONTAINED IN THE    //
  24. //    BINKLEYTERM  LICENSING  AGREEMENT.  IF YOU DO NOT FIND THE TEXT OF    //
  25. //    THIS  AGREEMENT IN ANY OF THE  AFOREMENTIONED FILES,  OR IF YOU DO    //
  26. //    NOT HAVE THESE FILES,  YOU  SHOULD  IMMEDIATELY CONTACT BIT BUCKET    //
  27. //    SOFTWARE CO.  AT ONE OF THE  ADDRESSES  LISTED BELOW.  IN NO EVENT    //
  28. //    SHOULD YOU  PROCEED TO USE THIS FILE  WITHOUT HAVING  ACCEPTED THE    //
  29. //    TERMS  OF  THE  BINKLEYTERM  LICENSING  AGREEMENT,  OR  SUCH OTHER    //
  30. //    AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO.      //
  31. //                                                                          //
  32. //                                                                          //
  33. // You can contact Bit Bucket Software Co. at any one of the following      //
  34. // addresses:                                                               //
  35. //                                                                          //
  36. // Bit Bucket Software Co.        FidoNet  1:104/501, 1:343/491             //
  37. // P.O. Box 460398                AlterNet 7:42/1491                        //
  38. // Aurora, CO 80046               BBS-Net  86:2030/1                        //
  39. //                                Internet f491.n343.z1.fidonet.org         //
  40. //                                                                          //
  41. // Please feel free to contact us at any time to share your comments about  //
  42. // our software and/or licensing policies.                                  //
  43. //                                                                          //
  44. //--------------------------------------------------------------------------//
  45.  
  46. // Include this file before any other includes or defines!
  47.  
  48. #include "includes.h"
  49.  
  50. static int  LOCALFUNC btree (PV7RCB);
  51. static int  LOCALFUNC _btree (PV7RCB, long);
  52. static int  LOCALFUNC get7node (PV7RCB, long, struct _ndx far *);
  53. static int  LOCALFUNC unpk (char *instr, char *outp, int many);
  54. static int  LOCALFUNC addr_compare (void *, void *, int);
  55. static int  LOCALFUNC name_compare (void *, void *, int);
  56. static void LOCALFUNC set_vars(PV7NODE, ADDRP);
  57.  
  58. extern int  get_nodelist_name (ADDRP);
  59.  
  60. extern char *nodelist_base;
  61. extern char *nodelist_name;
  62.  
  63.                       // r. hoerner: added "far" statement 1/3/97
  64. static struct _ndx far *noderef = NULL; // far pointer index file
  65. static char aline[160];
  66.  
  67. static FILE *idx_fp, *dat_fp, *dtp_fp;
  68.  
  69. static int find_first;         // is this findfirst or findnext ?
  70.  
  71. static ADDR searchaddr;
  72. static char searchname[40];
  73.  
  74. static void *desired;
  75. static int desired_len;
  76. static int (LOCALFUNC * compare_fn) (void *key, void *desired, int len);
  77.  
  78. static PV7NODEL beginp, lastp, actp;
  79.  
  80. static DTPHEADER dtphdr;
  81.  
  82.  
  83. // call this function before you use any other V7* function!
  84.  
  85. int V7Initialize(void){
  86.  
  87.    if (node_index == NULL)
  88.        node_index = _fmalloc (sizeof (struct _ndx));
  89.  
  90.    if (!node_index)
  91.    {
  92.        status_line (MSG_TXT(M_NODELIST_MEM));
  93.        return V7_OUT_OF_MEMORY;
  94.    }
  95.  
  96.    if (noderef == NULL)
  97.        noderef = _fmalloc (sizeof (struct _ndx));
  98.  
  99.    if (!noderef)
  100.    {
  101.        status_line (MSG_TXT(M_NODELIST_MEM));
  102.        return V7_OUT_OF_MEMORY;
  103.    }
  104.  
  105.    return V7_SUCCESS;
  106. }
  107.  
  108. // call this function when you're finished with V7* functions
  109.  
  110. int V7Finish(void){
  111.  
  112.    if (node_index)
  113.        _ffree (node_index);
  114.    node_index = NULL;
  115.  
  116.    if (noderef)
  117.        _ffree (noderef);
  118.    noderef = NULL;
  119.  
  120.    return V7_SUCCESS;
  121. }
  122.  
  123. // builds names of V7 / V7+ files
  124.  
  125. void V7buildnames(PV7RCB p, char *IndexName, char *DataName, char *DTPName){
  126.   char *fmt="%s%s.%s";
  127.   sprintf(DataName,fmt,p->pszPath,p->pszName,"DAT");
  128.   if((p->miscflags&MF_v7plus)>0)
  129.     sprintf(DTPName, fmt,p->pszPath,p->pszName,"DTP");
  130.   switch(p->whichindex){
  131.     case WI_ndx:
  132.       sprintf(IndexName,fmt,p->pszPath,p->pszName,"NDX");
  133.       break;
  134.     case WI_sdx:
  135.       if(p->miscflags & MF_sysopndx)
  136.         sprintf(IndexName,fmt,p->pszPath,"SYSOP","NDX");
  137.       else
  138.         sprintf(IndexName,fmt,p->pszPath,p->pszName,"SDX");
  139.       break;
  140.     case WI_pdx:
  141.       sprintf(IndexName,fmt,p->pszPath,p->pszName,"PDX");
  142.       break;
  143.   }
  144. }
  145.  
  146. // find all matching V7 entries and return first of them
  147.  
  148. int V7FindFirst(PV7RCB p){
  149.  
  150.    char IndexName[PATHLEN], DataName[PATHLEN], DTPName[PATHLEN];
  151.    char last_name_first[26], midname[26], *c, *p2, *m;
  152.    int namelen;
  153.    
  154.    V7buildnames(p,IndexName,DataName,DTPName);
  155.    
  156.    if ((idx_fp = share_fopen (IndexName, read_binary, DENY_WRITE)) == NULL){
  157.        status_line (MSG_TXT(M_UNABLE_TO_OPEN), IndexName);
  158.        return (V7_IDX_OPENFAILED);   // no file, no work to do
  159.    }
  160.    if ((dat_fp = share_fopen (DataName, read_binary, DENY_WRITE)) == NULL){
  161.       status_line (MSG_TXT(M_UNABLE_TO_OPEN), DataName);
  162.       return (V7_DAT_OPENFAILED);      // no file, no work to do
  163.    }
  164.    if((p->miscflags&MF_v7plus)>0){
  165.      if ((dtp_fp = share_fopen (DTPName, read_binary, DENY_WRITE)) == NULL){
  166.         status_line (MSG_TXT(M_UNABLE_TO_OPEN), DTPName);
  167.         return (V7_DTP_OPENFAILED);    // no file, no work to do
  168.      }
  169.      if(fread(&dtphdr,sizeof(dtphdr),1,dtp_fp)<1)
  170.        return V7_DTP_READERROR;
  171.    }
  172.  
  173.    switch(p->whichindex){
  174.  
  175.      case WI_ndx:
  176.        searchaddr.Zone  = p->pV7Node->ZoneNumber;
  177.        searchaddr.Net   = p->pV7Node->NetNumber;
  178.        searchaddr.Node  = p->pV7Node->NodeNumber;
  179.        searchaddr.Point = p->pV7Node->HubNode;
  180.        compare_fn = addr_compare;
  181.        desired = &searchaddr;
  182.        desired_len = p->wLen;
  183.        break;
  184.  
  185.      case WI_sdx:
  186.        c = midname;                                // Start of temp name buff   
  187.        p2 = p->pV7Node->SysopName;                 // Point to start of name    
  188.        m = NULL;                                   // Init pointer to space     
  189.  
  190.        *c = *p2++;
  191.        while (*c)                                  // Go entire length of name  
  192.        {
  193.           if (*c == ' ')                           // Look for space            
  194.              m = c;                                // Save location             
  195.           c++;
  196.           *c = *p2++;
  197.        }
  198.     
  199.        if (m != NULL)                               // If we have a pointer,     
  200.        {
  201.           *m++ = '\0';                              // Terminate the first half  
  202.           (void) strcpy (last_name_first, m);       // Now copy the last name    
  203.           (void) strcat (last_name_first, ", ");    // Insert a comma and space  
  204.           (void) strcat (last_name_first, midname); // Finally copy first half   
  205.        }
  206.        else
  207.           (void) strcpy (last_name_first, midname); // Use whole name otherwise
  208.     
  209.        (void) fancy_str (last_name_first);         // Get caps in where needed  
  210.        namelen = (int) strlen (last_name_first);   // Calc length now           
  211.        namelen = min(25,namelen);
  212.     
  213.        strncpy(searchname, last_name_first, namelen);
  214.        searchname[namelen]='\0';
  215.     
  216.        compare_fn = name_compare;
  217.        desired = &searchname;
  218.        desired_len = namelen;
  219.        break;
  220.  
  221.      case WI_pdx:
  222.        // not implemented yet!
  223.        break;
  224.    }
  225.    find_first = 1;
  226.  
  227.    return V7FindNext(p);
  228. }
  229.  
  230. // return next match
  231.  
  232. int V7FindNext(PV7RCB p){
  233.    int ret;
  234.    PV7NODEL p1,p2;
  235.  
  236.    if(find_first){
  237.       beginp = lastp = actp = NULL;
  238.       if(btree(p)!=0)
  239.          return V7_FINDNEXT_END;
  240.    }
  241.  
  242.    if(find_first)
  243.       actp = beginp;
  244.    else
  245.       actp = actp->next;
  246.  
  247.    if(actp==NULL){               // if this is the end, free memory 
  248.       for(p1=beginp;p1;p1=p2){
  249.          p2=p1->next;
  250.          free(p1);
  251.       }
  252.       beginp=NULL;
  253.       ret = V7_FINDNEXT_END;
  254.    }else{
  255.       ret = V7_SUCCESS;
  256.       *(p->pV7Node) = actp->v7n;
  257.    }
  258.    find_first = 0;
  259.    return ret;
  260. }
  261.  
  262. // call this after findnext returns V7_FINDNEXT_END
  263.  
  264. int V7FindClose(PV7RCB p){
  265.    PV7NODEL p1,p2;
  266.  
  267.    p=p;   // Make compiler happy 
  268.  
  269.    if(beginp){
  270.       for(p1=beginp;p1;p1=p2){
  271.          p2=p1->next;
  272.          free(p1);
  273.       }
  274.    }
  275.    beginp=NULL;
  276.  
  277.    if(idx_fp){
  278.       fclose (idx_fp);
  279.       idx_fp = NULL;
  280.    }
  281.  
  282.    if(dat_fp){
  283.       fclose (dat_fp);
  284.       dat_fp = NULL;
  285.    }
  286.    
  287.    if((p->miscflags&MF_v7plus)>0){
  288.      if (dtp_fp){
  289.         fclose (dtp_fp);
  290.         dtp_fp = NULL;
  291.      }
  292.    }
  293.    
  294.    return V7_SUCCESS;
  295. }
  296.  
  297. // find a single match in V7
  298.  
  299. int V7Find(PV7RCB p){
  300.    int ret;
  301.    (void) V7Initialize();
  302.    ret=V7FindFirst(p);
  303.    (void) V7FindClose(p);
  304.    // (void) V7Finish();  // don't call this and avoid many malloc/free calls 
  305.    return ret;
  306. }
  307.  
  308. // conversion char -> minute of day (time is UTC!), see FSC-0062
  309.  
  310. short minute_of_day(char c) 
  311. {
  312.   char upper_c;
  313.   short hour, minutes;
  314.   upper_c=toupper(c);
  315.   
  316.   if(upper_c>'X')
  317.     return -1; // invalid ! 
  318.     
  319.   hour = upper_c - 'A';   // 00 .. 23 
  320.   minutes = hour * 60;
  321.   
  322.   if(islower(c))         // uppercase -> time=hh:00, lowercase -> time=hh:30 
  323.     minutes += 30;
  324.     
  325.   return minutes;
  326. }
  327.  
  328. // process raw nodelist flags
  329.  
  330. static int LOCALFUNC
  331. process_flag(V7NODE *pv7, char *rawflag)
  332. {
  333.   static short userflag;
  334.   char *p=rawflag;
  335.   if(!p)                  // init call 
  336.     userflag=0;           
  337.   else
  338.   {
  339.     if(toupper(*p)=='U'){   // from now on: user flags! 
  340.       userflag=1;
  341.       p++;
  342.     }
  343.     if(*p)                  // anything left (after ",U") ? 
  344.     {
  345.       // ,Txy online time flag as in FSC-0062 v3 !?  
  346.       if(userflag && !(pv7->NodeFlags&B_CM) && toupper(*p)=='T')
  347.       {
  348.         short start, end;
  349. //      status_line(" Online flags: %s", p+1);
  350.  
  351.         if ((start=minute_of_day (*++p))<0 || (end=minute_of_day (*++p))<0)
  352.           status_line(MSG_TXT (M_V7P_INVALID_TXY), rawflag);
  353.         else{
  354.           pv7->online_start = start;
  355.           pv7->online_end   = end;
  356.         }
  357.       }
  358.     }
  359.   }
  360.   return 0;
  361. }
  362.  
  363. // parse / process raw nodelist line
  364.  
  365. static int LOCALFUNC
  366. process_raw(V7NODE *pv7, char *raw)
  367. {
  368.   int field=0;
  369.   char *p;
  370.  
  371.   process_flag(pv7, NULL); // init flag function 
  372.   
  373.   if(*raw==','){
  374.     field++;   // first field is empty, but counts! 
  375.     raw++;
  376.   }
  377.  
  378.   pv7->rawFlags[0]='\0';
  379.     
  380.   for(p=strtok(raw,","); p; field++, p=strtok(NULL,","))
  381.   {
  382.     switch(field)
  383.     {
  384.        case 0:                         // Node, Hub, Host, Region, Zone 
  385.          strcpy(pv7->rawType,p);
  386.          break;
  387.          
  388.        case 1:                         // Zone/Net/Node/Point number    
  389.          break;                        // nothing to do with that yet!  
  390.          
  391.        case 2:                         // System name                   
  392.          strcpy(pv7->rawSystemName,p);
  393.          break;
  394.          
  395.        case 3:                         // Location / City               
  396.          strcpy(pv7->rawMiscInfo,p);
  397.          break;
  398.        
  399.        case 4:                         // Sysop                         
  400.          strcpy(pv7->rawSysopName,p);
  401.          break;
  402.  
  403.        case 5:                         // Phone                         
  404.        case 6:                         // Baud                          
  405.          break;                        // nothing to do with that yet!  
  406.          
  407.        default:                        // >=7: flags: CM,XA,...         
  408.          if(field>7)
  409.            strcat(pv7->rawFlags,",");
  410.          strcat(pv7->rawFlags,p);
  411.          process_flag(pv7, p);
  412.          break;
  413.     }
  414.   }
  415.   return 0;
  416. }
  417.  
  418. // V7 dat lookup at datpos
  419.  
  420. static int LOCALFUNC
  421. foundmatch(PV7RCB prcb, long datpos)
  422. {
  423.    struct _vers7 vers7;
  424.    char a_line[400], a_line2[256];
  425.    char *cp,*cp2;
  426.    long dtpoffset;
  427.    int i,unpack_len;
  428.    unsigned short fieldlen;
  429.    char fieldbuf[1024];
  430.  
  431.    PV7NODEL p;
  432.  
  433.    if((p = (PV7NODEL) calloc(1, sizeof(V7NODEL)))==NULL)
  434.       return 1;
  435.  
  436.    strcpy(lastfound_SysopName,"(unknown)");
  437.  
  438.    if(beginp==NULL)
  439.       beginp=p;
  440.    else
  441.       lastp->next=p;
  442.    lastp=p;
  443.    lastp->next=NULL;
  444.  
  445.    if (fseek (dat_fp, datpos, SEEK_SET)){           // point at record  
  446.       status_line (MSG_TXT(M_NODELIST_SEEK_ERR), prcb->pszName, "dat");
  447.       return 1;
  448.    }
  449.  
  450.    if (fread ((char *) &vers7, sizeof (struct _vers7), 1, dat_fp)!=1){
  451.       status_line (MSG_TXT(M_NODELIST_READ_ERR), prcb->pszName, "dat");
  452.       return 1;
  453.    }
  454.  
  455.    p->v7n.ulOffset   = datpos;
  456.  
  457.    p->v7n.ZoneNumber = vers7.Zone;
  458.    p->v7n.NetNumber  = vers7.Net;
  459.    p->v7n.NodeNumber = vers7.Node;
  460.    p->v7n.HubNode    = vers7.HubNode;
  461.    p->v7n.BaudRate   = 300*vers7.BaudRate;
  462.    p->v7n.ModemType  = vers7.ModemType;
  463.    p->v7n.NodeFlags  = vers7.NodeFlags;
  464.    p->v7n.RealCost   = vers7.CallCost;
  465.    p->v7n.Cost       = vers7.CallCost;      // ????? 
  466.  
  467.    (void) fread (p->v7n.PhoneNumber, vers7.Phone_len, 1, dat_fp);
  468.    (void) fread (p->v7n.Password,    vers7.Password_len, 1, dat_fp);
  469.  
  470.    (void) memset (a_line,  '\0', 400);
  471.    (void) memset (a_line2, '\0', 256);
  472.  
  473.    if (fread (a_line2, vers7.pack_len, 1, dat_fp)!=1){
  474.       status_line (MSG_TXT(M_NODELIST_READ_ERR), prcb->pszName, "dat");
  475.       return 1;
  476.    }
  477.  
  478.    unpack_len = unpk (a_line2, a_line, vers7.pack_len);
  479.  
  480.    cp = &a_line[0];
  481.  
  482.    // BBS / system name 
  483.    i = vers7.Bname_len;                                         
  484.    (void) memcpy (p->v7n.SystemName, cp, min (33, i));
  485.    cp += i;
  486.    unpack_len -= i;
  487.  
  488.    // Sysop name 
  489.    i = vers7.Sname_len;                                         
  490.    (void) memcpy (p->v7n.SysopName, cp, min (25, i));
  491.    cp += i;
  492.    unpack_len -= i;
  493.  
  494.    // City name 
  495.    i = vers7.Cname_len;                                         
  496.    (void) memcpy (p->v7n.MiscInfo, cp, min (29, i));
  497.    cp += i;
  498.    unpack_len -= i;
  499.    
  500.    
  501.    // TJW 970409 V7+ extensions 
  502.    
  503.    // check if there are 8 hex characters left == V7+ DTP offset 
  504.    
  505.    for(cp2=cp,i=0;*cp2 && i<8 && i<unpack_len;cp2++, i++)
  506.    {
  507.      if(!isxdigit(*cp2))
  508.        break;
  509.    }
  510.    
  511.    if((prcb->miscflags&MF_v7plus)>0){ // v7+ enabled and 
  512.      if(i==8){                        // v7+ DTP offs detected
  513. //     status_line(" V7+ extension detected. Processing fields ...");
  514.        
  515.        sscanf(cp, "%8lx", &dtpoffset);
  516.        
  517. //     status_line(" V7+ DTP offset-value: '%lx'", dtpoffset);
  518.        
  519.        if (fseek (dtp_fp, dtpoffset, SEEK_SET)){
  520.          status_line (MSG_TXT(M_NODELIST_SEEK_ERR), prcb->pszName, "dtp");
  521.          return 1;
  522.        }
  523.        
  524.        // skip DTPALLLNK structure (not used yet)
  525.        // skip DTPNODELNK structure, nodes only (not used yet)
  526.        if(vers7.NodeFlags&B_point)
  527.          fseek(dtp_fp, (long) dtphdr.control.AllFixSize, SEEK_CUR);
  528.        else  
  529.          fseek(dtp_fp, (long) dtphdr.control.AllFixSize
  530.                      + (long) dtphdr.control.AddFixSize, SEEK_CUR);
  531.        
  532.        fieldlen=0xFFFFU;
  533.        if (fread ((char *) &fieldlen, sizeof (fieldlen), 1, dtp_fp)!=1){
  534.           status_line (MSG_TXT(M_NODELIST_READ_ERR), prcb->pszName, "dtp");
  535.           return 1;
  536.        }
  537.        if(fieldlen!=0xFFFFU){
  538. //       status_line (" V7+ Field %d, len=%d", field, (int) fieldlen);
  539.          if (fread ((char *) &fieldbuf, (size_t) fieldlen, 1, dtp_fp)!=1){
  540.            status_line (MSG_TXT(M_NODELIST_READ_ERR), prcb->pszName, "dtp");
  541.            return 1;
  542.          }
  543. //       status_line (" V7+ Field %d: %s", field, fieldbuf);
  544.          process_raw(&(p->v7n), fieldbuf);
  545.        }
  546.      }else{
  547.        status_line ("!Version7 Plus enabled, but not detected in this record");
  548.        p->v7n.rawType[0]='\0';
  549.        p->v7n.rawFlags[0]='\0';
  550.        strcpy(p->v7n.rawSystemName,p->v7n.SystemName);
  551.        strcpy(p->v7n.rawMiscInfo,p->v7n.MiscInfo);
  552.        strcpy(p->v7n.rawSysopName,p->v7n.SysopName);
  553.      }
  554.    }else{ // V7+ not enabled, use V7 stuff
  555.      p->v7n.rawType[0]='\0';
  556.      p->v7n.rawFlags[0]='\0';
  557.      strcpy(p->v7n.rawSystemName,p->v7n.SystemName);
  558.      strcpy(p->v7n.rawMiscInfo,p->v7n.MiscInfo);
  559.      strcpy(p->v7n.rawSysopName,p->v7n.SysopName);
  560.    }
  561.    return 0;
  562. }
  563.  
  564. // compare function for name lookup
  565.  
  566. static int LOCALFUNC
  567. name_compare (void *key, void *desired, int _len)
  568. {
  569.     return (strnicmp ((char *) key, (char *) desired, (unsigned int) min (desired_len, _len)));
  570. }
  571.  
  572. // compare function for address lookup
  573.  
  574. static int LOCALFUNC
  575. addr_compare (void *key, void *desired, int _len)
  576. {
  577.     int k, len = desired_len;
  578.  
  579.     if(len>=2){
  580.        k = ((ADDRP) key)->Zone - ((ADDRP) desired)->Zone;
  581.        if (k)
  582.           return (k);
  583.     }else return 0;
  584.  
  585.     if(len>=4){
  586.        k = ((ADDRP) key)->Net - ((ADDRP) desired)->Net;
  587.        if (k)
  588.           return (k);
  589.     }else return 0;
  590.  
  591.     if(len>=6){
  592.        k = ((ADDRP) key)->Node - ((ADDRP) desired)->Node;
  593.        if (k)
  594.           return (k);
  595.     }else return 0;
  596.  
  597. // Node matches.
  598. //
  599. // The rule for points:
  600. //  1) If len == 6, treat key value for Point as Zero.
  601. //  2) Return comparison of key Point and desired Point.
  602.  
  603.     if (_len == 6)                  // spezial treatment for key point 
  604.         ((ADDRP) key)->Point = 0;
  605.  
  606.     if(len>=8){
  607.        k = ((ADDRP) key)->Point - ((ADDRP) desired)->Point;
  608.        if (k)
  609.           return (k);
  610.     }
  611.     return 0;
  612. }
  613.  
  614. // General V7 nodelist engine. Used by both the by-node and by-sysop
  615. // lookups.
  616. //
  617. // Thanks to Phil Becker for showing me how nice it looks in assembler.
  618. // It helped me see how nice it could be in C.
  619. //
  620. // (I know, Phil, it's still nicer in assembler!)
  621.  
  622. static int LOCALFUNC
  623. btree (PV7RCB prcb)
  624. {
  625.     if (!get7node(prcb, 0L, noderef))                   // Get CtlRec      
  626.        return 1;
  627.  
  628.     return _btree(prcb, noderef->ndx.CtlBlk.CtlRoot);   // start recursion 
  629. }
  630.  
  631. static int LOCALFUNC
  632. _btree (PV7RCB prcb, long record)
  633. {
  634.     struct _ndx nodeidx;
  635.     int j, j_done=-1, k=0, l, ret=0, count;
  636.     struct _IndxRef far *ip = NULL;
  637.     struct _LeafRef far *lp = NULL;
  638.     char far *tp;
  639.         char *np;
  640.  
  641.     if (!get7node (prcb, record * noderef->ndx.CtlBlk.CtlBlkSize,&nodeidx))
  642.         return 1;
  643.  
  644. // Follow the node tree until we either match a key right in the index
  645. // node, or locate the leaf node which must contain the entry.
  646.  
  647.     if (nodeidx.ndx.INodeBlk.IndxFirst != -1)  // INodeBlk 
  648.     {
  649.         count = nodeidx.ndx.INodeBlk.IndxCnt;  // count may be 0 
  650.         if (count == 0){
  651.            // status_line(">Down 1"); 
  652.            ret=_btree(prcb, nodeidx.ndx.INodeBlk.IndxFirst);
  653.            // status_line(">Up   1"); 
  654.         }else{
  655.            for (j = 0; j < count; j++)         // check 20 or less 
  656.            {
  657.                ip = &(nodeidx.ndx.INodeBlk.IndxRef[j]);
  658.                tp = (char far *) &nodeidx + ip->IndxOfs;
  659.  
  660.                k = l = ip->IndxLen; // binary length in bytes 
  661.                                     // addresses are stored as ADDR structs 
  662.                                     // names are stored as "2ndName, 1stName" 
  663.  
  664.                for (np = aline; k > 0; k--)
  665.                    *np++ = *tp++;
  666.  
  667.                k = (*compare_fn) ((void *) aline, desired, l); // k=key-desired 
  668.  
  669.                if (k > 0)
  670.                   break;
  671.  
  672.                if (k == 0)
  673.                {
  674.  
  675. // Key matches in the index node. Since we're just doing lookup, we
  676. // can assume its pointer is valid. If we were doing updates, that
  677. // assumption would not work, because leaf nodes update first. So in
  678. // an update environment, the entire code segment relating to k == 0
  679. // should not execute, and we should walk the tree all the way down.
  680.  
  681.                    if(j == 0){
  682.                       // status_line(">Down 2"); 
  683.                       ret=ret+_btree(prcb, nodeidx.ndx.INodeBlk.IndxFirst);
  684.                       // status_line(">Up   2"); 
  685.                    }else if(j-1!=j_done){
  686.                       // status_line(">Down 3"); 
  687.                       ret=ret+_btree(prcb, nodeidx.ndx.INodeBlk.IndxRef[j-1].IndxPtr);
  688.                       // status_line(">Up   3"); 
  689.                    }
  690.                    // foundmatch (nodeidx.ndx.INodeBlk.IndxRef[j].IndxData); 
  691.                    // status_line(">Down 4"); 
  692.                    ret=ret+_btree(prcb, nodeidx.ndx.INodeBlk.IndxRef[j].IndxPtr);
  693.                    // status_line(">Up   4"); 
  694.                    j_done = j;
  695.                }
  696.            }
  697.            if (k != 0){
  698.               if(j == 0){
  699.                  // status_line(">Down 5"); 
  700.                  ret=ret+_btree(prcb, nodeidx.ndx.INodeBlk.IndxFirst);
  701.                  // status_line(">Up   5"); 
  702.               }else if(j-1 != j_done){
  703.                  // status_line(">Down 6"); 
  704.                  ret=ret+_btree(prcb, nodeidx.ndx.INodeBlk.IndxRef[j-1].IndxPtr);
  705.                  // status_line(">Up   6"); 
  706.               }
  707.            }
  708.         }
  709.  
  710.     }else{ // LNodeBlk 
  711.  
  712.        count = nodeidx.ndx.LNodeBlk.IndxCnt; // count may be 0 
  713.  
  714.        // Search for a higher key 
  715.  
  716.        for (j = 0; j < count; j++) // check 30 or less 
  717.        {
  718.            lp = &(nodeidx.ndx.LNodeBlk.LeafRef[j]);
  719.            tp = (char far *) &nodeidx + lp->KeyOfs;
  720.  
  721.            k = l = lp->KeyLen;
  722.  
  723.            for (np = aline; k > 0; k--)
  724.                *np++ = *tp++;
  725.  
  726.            k = (*compare_fn) ((void *) aline, desired, l);
  727.  
  728.            if (k > 0)
  729.               break;
  730.            else
  731.            if (k == 0)
  732.               ret=ret+foundmatch (prcb, nodeidx.ndx.LNodeBlk.LeafRef[j].KeyVal);
  733.        }
  734.     }
  735.     return ret;
  736. }
  737.  
  738. // read index entry
  739.  
  740. static int LOCALFUNC
  741. get7node (PV7RCB prcb, long position, struct _ndx far * ndx)
  742. {
  743.     if(fseek (idx_fp, position, SEEK_SET))
  744.     {
  745.         status_line (MSG_TXT(M_NODELIST_SEEK_ERR), prcb->pszName, "?dx");
  746.         return (0);
  747.     }
  748.  
  749.     if (fread (ndx, sizeof (struct _ndx), 1, idx_fp) != 1)
  750.     {
  751.         status_line (MSG_TXT(M_NODELIST_READ_ERR), prcb->pszName, "?dx");
  752.         return (0);
  753.     }
  754.     return (1);
  755. }
  756.  
  757. // unpack a dense version of a symbol (base 40 polynomial)
  758.  
  759. static int LOCALFUNC
  760. unpk (char *instr, char *outp, int count)
  761. {
  762.     // This table has been modified to minimize searches 
  763.     static char unwrk[] = " EANROSTILCHBDMUGPKYWFVJXZQ-'0123456789";
  764.  
  765.     struct chars
  766.     {
  767.         unsigned char c1;
  768.         unsigned char c2;
  769.     };
  770.  
  771.     union
  772.     {
  773.         unsigned short w1;
  774.         struct chars d;
  775.     } u;
  776.  
  777.     register short i, j;        // MB int 
  778.     char obuf[4];
  779.     int outlen;
  780.  
  781.     outp[0] = '\0';
  782.     outlen = 0;
  783.     
  784.     while (count)
  785.     {
  786.         u.d.c1 = *instr++;
  787.         u.d.c2 = *instr++;
  788.         count -= 2;
  789.         for (j = 2; j >= 0; j--)
  790.         {
  791.             i = u.w1 % 40;
  792.             u.w1 /= 40;
  793.             obuf[j] = unwrk[i];
  794.         }
  795.         obuf[3] = '\0';
  796.         (void) strcat (outp, obuf);
  797.         outlen += 3;
  798.     }
  799.     return outlen;
  800. }
  801.  
  802. // these are for Binkley's use:
  803.  
  804. // address lookup
  805.  
  806. int
  807. ver7find (ADDRP opus_addr, int have_boss_data)
  808. {
  809.    ADDR faddr;
  810.    V7RCB v7rcb;
  811.    V7NODE v7n;
  812.  
  813.    strcpy(lastfound_SysopName,"(unknown)");
  814.    have_boss_data = have_boss_data;     // make compiler happy 
  815.  
  816.    (void) memset (&newnodedes, 0, sizeof (struct _newnode));
  817.  
  818.    memset (&v7rcb, 0, sizeof(v7rcb));
  819.    memset (&v7n, 0, sizeof(v7n));
  820.    v7rcb.pV7Node = &v7n;
  821.  
  822.    if (!get_nodelist_name (opus_addr))
  823.        return 0;
  824.  
  825.    v7rcb.pszPath = (PSZ)net_info;
  826.    v7rcb.pszName = (PSZ)nodelist_base;
  827.    v7rcb.whichindex = WI_ndx;
  828.  
  829.    v7rcb.miscflags |= (version7>1) ? 1:0;
  830.    v7rcb.miscflags |= (sysopndx) ? MF_sysopndx:0;
  831.  
  832.    v7n.ZoneNumber = opus_addr->Zone;
  833.    v7n.NetNumber  = opus_addr->Net;
  834.    v7n.NodeNumber = opus_addr->Node;
  835.    v7n.HubNode    = opus_addr->Point;
  836.    v7rcb.wLen     = 8;
  837.  
  838.    if(V7Find(&v7rcb)==V7_SUCCESS){
  839.       set_vars(&v7n, &faddr);
  840.       return 1;
  841.    }else
  842.       return 0;
  843. }
  844.  
  845. // name lookup
  846.  
  847. void
  848. opususer (char *name, ADDRP faddr)
  849. {
  850.    V7RCB v7rcb;
  851.    V7NODE v7n;
  852.    int namelen;
  853.  
  854.    strcpy(lastfound_SysopName,"(unknown)");
  855.    faddr->Zone = faddr->Net = faddr->Node = faddr->Point = (unsigned short) -1;
  856.    faddr->Domain = NULL;
  857.  
  858.    (void) memset (&newnodedes, 0, sizeof (struct _newnode));
  859.  
  860.    memset (&v7rcb, 0, sizeof(v7rcb));
  861.    memset (&v7n, 0, sizeof(v7n));
  862.    v7rcb.pV7Node = &v7n;
  863.  
  864.    if (nodelist_base == NULL)
  865.        get_nodelist_name (&my_addr);
  866.  
  867.    v7rcb.pszPath = (PSZ)net_info;
  868.    v7rcb.pszName = (PSZ)nodelist_base;
  869.    v7rcb.whichindex = WI_sdx;
  870.  
  871.    v7rcb.miscflags |= (version7>1) ? 1:0;
  872.    v7rcb.miscflags |= (sysopndx) ? MF_sysopndx:0;
  873.  
  874.    namelen = min(25,strlen(name));
  875.    strncpy(v7n.SysopName, name, namelen);
  876.    v7n.SysopName[namelen]='\0';
  877.    v7rcb.wLen = namelen;
  878.  
  879.    if(V7Find(&v7rcb)==V7_SUCCESS){
  880.       set_vars(&v7n, faddr);
  881.    }
  882. }
  883.  
  884. // set BT's variables
  885.  
  886. static void LOCALFUNC
  887. set_vars(PV7NODE p, ADDRP faddr){
  888.  
  889.    newnodedes.NetNumber  = p->NetNumber;
  890.    newnodedes.NodeNumber = p->NodeNumber;
  891.    newnodedes.HubNode    = p->HubNode;
  892.  
  893.    newnodedes.BaudRate   = (byte)(p->BaudRate/300);
  894.    newnodedes.ModemType  = p->ModemType;
  895.    newnodedes.NodeFlags  = p->NodeFlags;
  896.  
  897.    GetAltModemflag((word *)&newnodedes.ModemType,faddr);
  898.    GetAltFidoFlag ((word *)&newnodedes.NodeFlags,faddr);
  899.  
  900.    newnodedes.Cost       = p->RealCost;
  901.    newnodedes.RealCost   = p->RealCost;
  902.  
  903.    (void) strcpy (lastfound_SysopName, p->SysopName);
  904.    if (!nofancystrings)
  905.      (void) fancy_str (lastfound_SysopName);
  906.  
  907.    (void) strcpy (newnodedes.SystemName, p->SystemName);
  908.    if (!nofancystrings)
  909.      (void) fancy_str (newnodedes.SystemName);
  910.  
  911.    (void) strcpy (newnodedes.PhoneNumber, p->PhoneNumber);
  912.  
  913.    (void) strcpy (newnodedes.MiscInfo, p->MiscInfo);
  914.    if (!nofancystrings)
  915.      (void) fancy_str (newnodedes.MiscInfo);
  916.  
  917.    (void) memcpy (newnodedes.Password, p->Password, 8);
  918.  
  919.    found_zone  = p->ZoneNumber;
  920.    found_net   = p->NetNumber;
  921.  
  922.    faddr->Zone = p->ZoneNumber;
  923.    faddr->Net  = p->NetNumber;
  924.    faddr->Node = p->NodeNumber;
  925.    if (p->NodeFlags & B_point)
  926.       faddr->Point = p->HubNode;
  927.    else
  928.       faddr->Point = 0;
  929.    faddr->Domain = NULL;
  930. }
  931.  
  932.